package com.naiterui.ehp.bs.doctor.controller;

import cn.hutool.core.collection.CollectionUtil;
import com.naiterui.common.repository.page.PageParamVO;
import com.naiterui.common.repository.page.PageVO;
import com.naiterui.ehp.bp.constants.SwaggerTag;
import com.naiterui.ehp.bp.support.context.ResourceHolder;
import com.naiterui.ehp.bp.support.exception.BusinessException;
import com.naiterui.ehp.bp.support.exception.PublicService;
import com.naiterui.ehp.bp.support.exception.ResponseVO;
import com.naiterui.ehp.bp.support.security.SettingConfig;
import com.naiterui.ehp.bp.utils.lang.StringUtil;
import com.naiterui.ehp.bp.utils.sort.ABCUtil.ABCVO;
import com.naiterui.ehp.bs.doctor.exception.ExceptionCodes;
import com.naiterui.ehp.bs.doctor.service.IPatientDiseaseService;
import com.naiterui.ehp.bs.doctor.service.IPatientGroupService;
import com.naiterui.ehp.bs.doctor.service.IPatientService;
import com.naiterui.ehp.bs.doctor.vo.DeletePatientVO;
import com.naiterui.ehp.bs.doctor.vo.MemberVO;
import com.naiterui.ehp.bs.doctor.vo.MyPatientVO;
import com.naiterui.ehp.bs.doctor.vo.PatientDetailVo;
import com.naiterui.ehp.bs.doctor.vo.PatientDiseaseVO;
import com.naiterui.ehp.bs.doctor.vo.PatientGroupVo;
import com.naiterui.ehp.bs.doctor.vo.PatientInfoVO;
import com.naiterui.ehp.bs.doctor.vo.PatientRemarkInfoVO;
import com.naiterui.ehp.bs.doctor.vo.PatientSimpleVO;
import com.naiterui.ehp.bs.doctor.vo.PatientVo;
import com.naiterui.ehp.bs.doctor.vo.casefile.CaseDetailVO;
import com.naiterui.ehp.bs.doctor.vo.casefile.CaseListVO;
import com.naiterui.ehp.bs.doctor.vo.patient.FamilyLiteVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import springfox.documentation.annotations.ApiIgnore;

import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.List;

/**
 * 患者列表和患者详情控制类
 *
 * @version 2015年6月21日 下午4:17:14 by chenlin
 * @Description 概述
 */
@Validated
@Api(tags = {SwaggerTag.DOCTOR + SwaggerTag.PATIENT_MANAGER})
@Controller
@RestController
@RequestMapping("ad/patient")
public class AdPatientController {

    private static final Logger LOGGER = LoggerFactory.getLogger(AdPatientController.class);

    @Autowired
    private IPatientService patientService;
    @Autowired
    private IPatientGroupService patientGroupService;
    @Autowired
    private IPatientDiseaseService patientDiseaseService;

    /**
     * <查询新增患者信息>
     * <详细描述>
     *
     * @param doctorId
     * @param patientIds
     *
     * @return String <返回值描述>
     *
     * @Throws 异常信息
     * @History 2015年6月22日 下午9:28:58 by chenlin
     */
    @ApiOperation(value = "新患者列表",notes = "按推送的新关注患者ID查询患者信息列表", httpMethod = "GET")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "doctorId", value = "医生ID", dataType = "long", paramType = "query", required = true),
            @ApiImplicitParam(name = "patientIds", value = "患者ID列表(英文逗号分隔)", dataType = "String", paramType = "query", required = true),
    })
    @RequestMapping("/newList")
    public ResponseVO<List<PatientVo>> newPatientList(Long doctorId, String patientIds) throws Exception {
        LOGGER.info("查询新增患者信息 请求参数：doctorId = {}, patientIds = {}", doctorId, patientIds);

        if (StringUtils.isBlank(patientIds)) {
            LOGGER.info("医生id={},查询的新增患者列表为:{}", doctorId, patientIds);
            throw new BusinessException(ExceptionCodes.PATIENT_NEW_LIST_NULL);
        }

        List<PatientVo> patientList = this.patientService.findPatientByPatientId(doctorId, patientIds);

        if (CollectionUtil.isEmpty(patientList)) {
            LOGGER.info("医生id={},查询的新增患者列表为:{}", doctorId, patientIds);
            throw new BusinessException(ExceptionCodes.PATIENT_NEW_LIST_NULL);
        }
        return PublicService.returnResponseVO(ExceptionCodes.SUCCESS, patientList);
    }

    /**
     * <获取患者的基本详情信息>
     * <详细描述>
     *
     * @param doctorId
     * @param patientId
     * @return String <返回值描述>
     *
     * @Throws 异常信息
     * @History 2015年6月22日 下午3:43:35 by chenlin
     */
    @ApiOperation(value = "患者详情", httpMethod = "GET")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "doctorId", value = "医生ID", dataType = "long", paramType = "query", required = true),
            @ApiImplicitParam(name = "patientId", value = "患者ID", dataType = "long", paramType = "query", required = true),
    })
    @RequestMapping("/detail")
    @ResponseBody
    public ResponseVO<PatientDetailVo> detail(Long doctorId, Long patientId) throws BusinessException {
        if (doctorId == null || patientId == null) {
            throw new BusinessException(ExceptionCodes.PARAM_ERROR);
        }

        PatientDetailVo detail = this.patientService.getPatientDetail(doctorId, patientId);
        return PublicService.returnResponseVO(ExceptionCodes.SUCCESS, detail);
    }


    /**
     * <根据患者名称首字母分为ABC列表>
     * <详细描述>
     *
     * @param doctorId
     * @param groupId
     *
     * @return String <返回值描述>
     *
     * @Throws 异常信息
     * @History 2015年6月22日 下午9:28:12 by chenlin
     */
    @ApiOperation(value = "患者ABC列表", httpMethod = "GET")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "doctorId", value = "医生ID", dataType = "long", paramType = "query", required = true),
            @ApiImplicitParam(name = "groupId", value = "分组ID", dataType = "long", paramType = "query"),
    })
    @RequestMapping("/abcList")
    @ResponseBody
    public ResponseVO<List<ABCVO<PatientVo>>> abcList(Long doctorId, @RequestParam(required = false) Long groupId) throws Exception {
        List<ABCVO<PatientVo>> list = this.patientService.findPatientABCList(doctorId, groupId);

        return PublicService.returnResponseVO(ExceptionCodes.SUCCESS, list);
    }

    /**
     * 我的患者列表（普通+特别关心）
     *
     * @param doctorId
     *
     * @return
     *
     * @Description
     */
    @RequestMapping("/my")
    @ApiOperation(value = "我的患者列表", notes = "我的患者列表（普通+特别关心）", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiImplicitParams({@ApiImplicitParam(name = "doctorId", value = "医生id", required = true, dataType = "long", paramType = "query")})
    public ResponseVO<MyPatientVO> myPatientList(@NotNull(message = "医生ID不能为null") Long doctorId) throws Exception {
        LOGGER.info("获取我的患者列表 医生：{}", doctorId);
        // 获取患者信息
        MyPatientVO patients = this.patientService.getMyPatients(doctorId);
        return PublicService.returnResponseVO(ExceptionCodes.SUCCESS, patients);
    }

    /**
     * 添加/取消特别关注
     * PatientController.specPatient()
     *
     * @param doctorId
     * @param patientId
     *
     * @return
     *
     * @Author Amber
     * @Date 2016年6月15日
     * @since 1.0.0
     */
    @ApiOperation(value = "操作特别关注(添加或取消)")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "doctorId", value = "医生ID", dataType = "long", paramType = "form", required = true),
            @ApiImplicitParam(name = "patientId", value = "患者ID", dataType = "long", paramType = "form", required = true),
    })
    @PostMapping(value = "/spec")
    @ResponseBody
    @ApiIgnore
    public void specPatient(Long doctorId, Long patientId) throws BusinessException {
        LOGGER.info("添加或取消特别关注 医生：{};患者：{}", doctorId, patientId);

        // 参数校验
        if (doctorId == null || patientId == null) {
            throw new BusinessException(ExceptionCodes.PARAM_ERROR);
        }
        // 更新特别关注状态
        this.patientService.saveSpecPatient(doctorId, patientId);
    }

    /**
     * 获取患者病历档案列表 PatientController.getCaseList()<BR> <P>Author : Amber </P>
     * <P>Date : 2015年9月17日 </P>
     *
     * @param doctorId
     * @param patientId
     * @param pageParamVO
     *
     * @return
     */
    @ApiOperation(value = "获取患者病历档案(已废弃?)", httpMethod = "GET")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "doctorId", value = "医生ID", dataType = "long", paramType = "query", required = true),
            @ApiImplicitParam(name = "patientId", value = "患者ID", dataType = "long", paramType = "query", required = true),
    })
    @RequestMapping("case/list")
    @ResponseBody
    public PageVO<CaseListVO> getCaseList(Long doctorId, Long patientId, PageParamVO pageParamVO) throws BusinessException {
        // 参数校验
        if (doctorId == null || patientId == null) {
            // 参数不合法日志
            LOGGER.error("patient case list params error doctorId {},patientId {}, pageParamVO {}", doctorId,
                         patientId, pageParamVO);
            throw new BusinessException(ExceptionCodes.PARAM_ERROR);
        }
        // 正常请求日志，info
        LOGGER.info("patient case list doctorId {}, patientId {}, pageParamVO {}", doctorId, patientId, pageParamVO);
        return this.patientService.getCaseList(doctorId, patientId, pageParamVO.getPage(), pageParamVO.getNum());
    }

    /**
     * 查看患者病例档案详情 解决V1.4安卓客户端对于大于8张图片崩溃的问题，在1.4之前版本，病历档案检验单最多返回4张
     * PatientController.getCaseDetail()
     *
     * @param doctorId
     * @param patientId
     * @param caseId
     *
     * @return
     *
     * @Author Amber
     * @Date 2015年12月14日
     * @end 1.4.0
     * @since 1.0.0
     */
    @ApiOperation(value = "获取患者病历档案详情(已废弃?)", httpMethod = "GET")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "doctorId", value = "医生ID", dataType = "long", paramType = "query", required = true),
            @ApiImplicitParam(name = "patientId", value = "患者ID", dataType = "long", paramType = "query", required = true),
            @ApiImplicitParam(name = "caseId", value = "病例ID", dataType = "String", paramType = "query", required = true),
    })
    @RequestMapping("case/detail")
    @ResponseBody
    public CaseDetailVO getCaseDetail(Long doctorId, Long patientId, String caseId) throws BusinessException {
        // 参数校验
        if (doctorId == null || patientId == null || caseId == null) {
            // 参数不合法日志
            LOGGER.error("patient case detail params error doctorId {},patientId {}, caseId {}", doctorId, patientId, caseId);
            throw new BusinessException(ExceptionCodes.INVALID_REQUEST);
        }
        return this.patientService.getCaseDetail(doctorId, patientId, caseId);
    }


    /**
     * 患者病历页：个人信息+所属分组+病情
     *
     * @param doctorId  医生ID
     * @param patientId 患者ID
     *
     * @return
     *
     * @throws BusinessException
     * @Description
     * @History 2017年6月7日 by wangchuan
     */
    @ApiOperation(value = "患者病历页基本信息(已废弃?)",
            notes = "患者病历页基本信息。注意：节点patientGroup中的groupCount、isIncluded字段在本接口中忽略！patientRemarkInfo" +
                    ".showTips的值提示需要提醒填写患者信息时patientRemarkInfo节点中的数据为患者填写的个人信息否则该节点为医生备注后的患者信息",
            httpMethod = "POST")
    @ApiImplicitParams({@ApiImplicitParam(name = "doctorId", value = "医生ID", required = true, dataType = "long", paramType = "query"),
            @ApiImplicitParam(name = "patientId", value = "患者ID", required = true, dataType = "long", paramType = "query")})
    @RequestMapping("/detail/remark")
    @ResponseBody
    public ResponseVO<PatientInfoVO> getRemarkDetail(Long doctorId, Long patientId) throws BusinessException {
        LOGGER.info("患者病历页基本信息：doctorId={}, patientId={}", doctorId, patientId);
        if (doctorId == null || patientId == null) {
            LOGGER.info("患者病历页基本信息，医生ID或者患者ID为空");
            throw new BusinessException(ExceptionCodes.PARAM_ERROR);
        }
        //判断医患关系
        this.patientService.isdDleteDoctorPatientRelation(doctorId, patientId);

        PatientInfoVO patientInfo = new PatientInfoVO();
        // 患者相关信息[包含了是否需要提示(患者填写的信息)的逻辑]
        PatientRemarkInfoVO remarkInfo = this.patientService.getPatientInfo(doctorId, patientId);

        // 患者所在分组名，list
        List<PatientGroupVo> patientGroupList = this.patientGroupService.getGroupListByPatient(doctorId, patientId);

        // 医生备注病情
        PatientDiseaseVO patientDisease = this.patientDiseaseService.getRemarkDisease(doctorId, patientId);

        // 病历页筛选条件
        List<MemberVO> relationList = this.patientService.getScreenList(doctorId, patientId);

        patientInfo.setPatientRemarkInfo(remarkInfo);
        patientInfo.setPatientGroupList(patientGroupList);
        patientInfo.setPatientDisease(patientDisease);
        patientInfo.setRelationList(relationList);
        return PublicService.returnResponseVO(ExceptionCodes.SUCCESS, patientInfo);
    }

    /**
     * 医生修改患者备注信息
     *
     * @param doctorId      医生id
     * @param patientId     患者id
     * @param patientInfoVO 修改后基本信息
     *
     * @return
     *
     * @throws BusinessException
     * @Description
     * @History 2017年6月9日 by wangchuan
     */
    @ApiOperation(value = "修改患者备注信息", notes = "医生编辑对患者的备注个人信息", httpMethod = "POST")
    @ApiImplicitParams({@ApiImplicitParam(name = "doctorId", value = "医生ID", required = true, dataType = "long", paramType = "query"),
            @ApiImplicitParam(name = "patientId", value = "患者ID", required = true, dataType = "long", paramType = "query")})
    @RequestMapping("/modify")
    @ResponseBody
    public ResponseVO<Void> modifyRemarkInfo(Long doctorId, Long patientId, PatientRemarkInfoVO patientInfoVO) throws BusinessException {
        LOGGER.info("医生修改患者备注信息，doctorId={}, patientId={}", doctorId, patientId);
        if (doctorId == null || patientId == null || patientInfoVO == null) {
            LOGGER.info("医生修改患者备注信息，医生ID、患者ID或者个人信息参数为空");
            throw new BusinessException(ExceptionCodes.PARAM_ERROR);
        }

        LOGGER.debug("医生修改患者备注信息，备注信息：{}", patientInfoVO.toString());
        // 保存或更新患者备注信息
        this.patientService.saveOrUpdatePatientInfo(doctorId, patientId, patientInfoVO);

        return PublicService.returnResponseVO(ExceptionCodes.SUCCESS);
    }

    /**
     * 分页获取{30天}内新患者列表
     *
     * @param doctorId 医生ID
     *
     * @return
     *
     * @throws BusinessException
     * @Description
     * @History 2017年6月9日 by wangchuan
     */
    @ApiOperation(value = "分页获取新患者列表", notes = "分页获取{30天内}新患者列表", httpMethod = "POST")
    @ApiImplicitParams({@ApiImplicitParam(name = "doctorId", value = "医生ID", required = true, dataType = "long", paramType = "query")})
    @RequestMapping("/list/new")
    @ResponseBody
    public ResponseVO<PageVO<PatientRemarkInfoVO>> getPagedNewPatientList(Long doctorId, PageParamVO pageParamVO) throws BusinessException {
        LOGGER.info("分页获取新患者列表：doctorId={}, pageParamVO={}", doctorId, pageParamVO);
        if (doctorId == null) {
            LOGGER.info("新患者列表，医生ID为空");
            throw new BusinessException(ExceptionCodes.PARAM_ERROR);
        }
        // 已经分页并排序的患者列表
        PageVO<PatientRemarkInfoVO> pagedNewPatientList = this.patientService.getPagedPatientByPeriods(doctorId, pageParamVO);
        return PublicService.returnResponseVO(ExceptionCodes.SUCCESS, pagedNewPatientList);
    }

    /**
     * 获取患者简略信息
     *
     * @param doctorId
     * @param patientId
     *
     * @return
     *
     * @throws BusinessException
     * @Description 发送处方笺后，可能有反写姓名逻辑，首页对话列表、对话框页等处更新显示患者姓名
     * @author wangchuan
     * @Date 2017年8月8日
     * @since V2.9.0
     */
    @ApiOperation(value = "获取患者简略信息", notes = "根据患者id获取患者简略信息", httpMethod = "POST")
    @ApiImplicitParams({@ApiImplicitParam(name = "doctorId", value = "医生ID", required = true, dataType = "long", paramType = "query"),
            @ApiImplicitParam(name = "patientId", value = "患者ID", required = true, dataType = "long", paramType = "query")})
    @RequestMapping("/info/simple")
    @ResponseBody
    public ResponseVO<PatientSimpleVO> getPatientSimpleInfo(Long doctorId, Long patientId) throws BusinessException {
        LOGGER.info("获取患者简略信息：doctorId={}, patientId={}", doctorId, patientId);
        if (doctorId == null || patientId == null) {
            throw new BusinessException(ExceptionCodes.PARAM_ERROR);
        }
        PatientSimpleVO info = this.patientService.getPatientSimpleInfo(doctorId, patientId);
        return PublicService.returnResponseVO(ExceptionCodes.SUCCESS, info);
    }

    /**
     * 删除患者
     *
     * @param doctorId  医生ID
     * @param patientId 患者ID
     *
     * @return
     */
    @ApiOperation(value = "删除患者", notes = "删除患者")
    @ApiImplicitParams({@ApiImplicitParam(name = "doctorId", value = "医生ID", required = true, dataType = "long", paramType = "query"),
            @ApiImplicitParam(name = "patientId", value = "患者ID", required = true, dataType = "long", paramType = "query")})
    @GetMapping("delete")
    public ResponseVO<Void> delete(@NotNull(message = "医生ID不能为null") Long doctorId,
                                   @NotNull(message = "患者ID不能为null") Long patientId) throws BusinessException {
        LOGGER.info("删除患者 请求参数：doctorId = {}, patientId = {}", doctorId, patientId);
        this.patientService.deletePatientRelation(doctorId, patientId);
        return PublicService.returnResponseVO(ExceptionCodes.SUCCESS);
    }

    /**
     * 恢复医患关系
     *
     * @param patientIds 患者id
     * @param doctorId   医生id
     *
     * @throws BusinessException
     */
    @GetMapping("recover")
    @ApiOperation(value = "批量恢复患者", notes = "批量恢复患者")
    @ApiImplicitParams({@ApiImplicitParam(name = "doctorId", value = "医生ID", required = true, dataType = "long", paramType = "query"),
            @ApiImplicitParam(name = "patientIds", value = "患者ID集合，用逗号分隔", required = true, dataType = "string", paramType = "query")})
    public ResponseVO<Void> patientRecover(@NotNull(message = "医生id不能为null") Long doctorId, @NotEmpty(message = "患者id不能为null") String patientIds) {
        LOGGER.info("恢复医患关系 请求参数：doctorId = {}, patientIds = {}", doctorId, patientIds);
        this.patientService.updatePatientRecover(doctorId, StringUtil.convertLongStr2List(patientIds, ","));
        return PublicService.returnResponseVO(ExceptionCodes.SUCCESS);
    }

    @GetMapping("delete/list")
    @ApiOperation(value = "获取删除患者列表", notes = "获取删除患者列表")
    @ApiImplicitParams({@ApiImplicitParam(name = "doctorId", value = "医生ID", required = true, dataType = "long", paramType = "query"),})
    public ResponseVO<List<DeletePatientVO>> deleteList(@NotNull(message = "医生ID不能为null") Long doctorId) {
        LOGGER.info("获取删除患者列表 请求参数：doctorId = {}", doctorId);
        List<DeletePatientVO> list = this.patientService.getPatientDeleteList(doctorId);
        return PublicService.returnResponseVO(list);
    }

    /**
     * 家庭成员列表：只显示有健康档案的家庭成员
     *
     * @param patientId
     *
     * @return
     *
     * @throws BusinessException
     */
    @PostMapping("family/list")
    @ApiOperation(value = "获取患者家庭成员列表(已废弃?)", notes = "获取患者家庭成员列表", httpMethod = "POST")
    @ApiImplicitParams({@ApiImplicitParam(name = "patientId", value = "患者ID", required = true, dataType = "long", paramType = "query")})
    public ResponseVO<List<FamilyLiteVO>> list(Long patientId) throws BusinessException {
        if (null == patientId) {
            patientId = (Long) ResourceHolder.getResource(SettingConfig.PATIENT_ID);
        }
        LOGGER.info("获取家庭成员列表：patientId={}", patientId);
        return PublicService.returnResponseVO(this.patientService.findFamilyByPatientId(patientId));
    }


    /**
     * 获取生命汇His系统H5页面地址
     *
     * @param inquirerId
     *
     * @return
     */
    @GetMapping("offline/record/info")
    @ApiOperation(value = "获取就诊人线下病历信息H5页面", notes = "获取就诊人线下病历信息H5页面", httpMethod = "GET")
    @ApiImplicitParams({ @ApiImplicitParam(name = "inquirerId", value = "就诊人ID", required = true, dataType = "long", paramType = "query") })
    public ResponseVO<String> getHisH5Url(Long inquirerId) throws BusinessException {
        return PublicService.returnResponseVO(this.patientService.getHisH5Url(inquirerId));
    }
}
